<template>
	<u-popup :maskCloseAble="maskCloseAble" mode="bottom" :popup="false" v-model="value" length="auto" :safeAreaInsetBottom="safeAreaInsetBottom" @close="close" :z-index="uZIndex">
		<view class="u-datetime-picker">
			<view class="u-picker-header" @touchmove.stop.prevent="">
				<view class="u-btn-picker u-btn-picker--tips" 
					:style="{ color: cancelColor }" 
					hover-class="u-opacity" 
					:hover-stay-time="150" 
					@tap="getResult('cancel')"
				>{{cancelText}}</view>
				<view class="u-picker__title">{{ title }}</view>
				<view
					class="u-btn-picker u-btn-picker--primary"
					:style="{ color: moving ? cancelColor : confirmColor }"
					hover-class="u-opacity"
					:hover-stay-time="150"
					@touchmove.stop=""
					@tap.stop="getResult('confirm')"
				>
					{{confirmText}}
				</view>
			</view>
			<view class="u-picker-body">
				<picker-view v-if="mode == 'time'" :value="valueArr" @change="change" class="u-picker-view" @pickstart="pickstart" @pickend="pickend">
					<picker-view-column v-if="!reset && params.year">
						<view class="u-column-item" v-for="(item, index) in years" :key="index">
							{{ item }}
							<text class="u-text" v-if="showTimeTag">年</text>
						</view>
					</picker-view-column>
					<picker-view-column v-if="!reset && params.month">
						<view class="u-column-item" v-for="(item, index) in months" :key="index">
							{{ formatNumber(item) }}
							<text class="u-text" v-if="showTimeTag">月</text>
						</view>
					</picker-view-column>
					<picker-view-column v-if="!reset && params.day">
						<view class="u-column-item" v-for="(item, index) in days" :key="index">
							{{ formatNumber(item) }}
							<text class="u-text" v-if="showTimeTag">日</text>
						</view>
					</picker-view-column>
					<picker-view-column v-if="!reset && params.hour">
						<view class="u-column-item" v-for="(item, index) in hours" :key="index">
							{{ formatNumber(item) }}
							<text class="u-text" v-if="showTimeTag">时</text>
						</view>
					</picker-view-column>
					<picker-view-column v-if="!reset && params.minute">
						<view class="u-column-item" v-for="(item, index) in minutes" :key="index">
							{{ formatNumber(item) }}
							<text class="u-text" v-if="showTimeTag">分</text>
						</view>
					</picker-view-column>
					<picker-view-column v-if="!reset && params.second">
						<view class="u-column-item" v-for="(item, index) in seconds" :key="index">
							{{ formatNumber(item) }}
							<text class="u-text" v-if="showTimeTag">秒</text>
						</view>
					</picker-view-column>
				</picker-view>
				<picker-view v-else-if="mode == 'selector'" :value="valueArr" @change="change" class="u-picker-view" @pickstart="pickstart" @pickend="pickend">
					<picker-view-column v-if="!reset">
						<view class="u-column-item" v-for="(item, index) in range" :key="index">
							<view class="u-line-1">{{ getItemValue(item, 'selector') }}</view>
						</view>
					</picker-view-column>
				</picker-view>
				<picker-view v-else-if="mode == 'multiSelector'" :value="valueArr" @change="change" class="u-picker-view" @pickstart="pickstart" @pickend="pickend">
					<picker-view-column v-if="!reset" v-for="(item, index) in range" :key="index">
						<view class="u-column-item" v-for="(item1, index1) in item" :key="index1">
							<view class="u-line-1">{{ getItemValue(item1, 'multiSelector') }}</view>
						</view>
					</picker-view-column>
				</picker-view>
			</view>
		</view>
	</u-popup>
</template>

<script>


export default {
	name: 'y-picker',
	props: {
		
		params: {
			type: Object,
			default() {
				return {
					year: true,
					month: true,
					day: true,
					hour: false,
					minute: false,
					second: false,
					province: true,
					city: true,
					area: true,
					timestamp: true,
				};
			}
		},
		
		range: {
			type: Array,
			default() {
				return [];
			}
		},
		
		defaultSelector: {
			type: Array,
			default() {
				return [0];
			}
		},
		
		rangeKey: {
			type: String,
			default: ''
		},
		
		mode: {
			type: String,
			default: 'time'
		},
		
		start:{
			type:Object,
			default(){
				return{
					year: 1990,
					month: 1,
					day: 1,
					hour: 0,
					minute: 0,
					second: 0,
				}
			}
		},
		
		end:{
			type:Object,
			default(){
				const now = new Date()
				return{
					year: now.getFullYear(),
					month: now.getMonth()+1,
					day: now.getDate(),
					hour: now.getHours(),
					minute: now.getMinutes(),
					second: now.getSeconds()
				}
			}
		},
		
		cancelColor: {
			type: String,
			default: '#606266'
		},
		
		confirmColor: {
			type: String,
			default: '#2979ff'
		},
		
		defaultTime: {
			type: String,
			default(){
				return new Date().Format('yyyy-MM-dd HH:mm:ss')
			}
		},
		
		showTimeTag: {
			type: Boolean,
			default: true
		},
		safeAreaInsetBottom: {
			type: Boolean,
			default: false
		},
		
		maskCloseAble: {
			type: Boolean,
			default: true
		},
		
		value: {
			type: Boolean,
			default: false
		},
		
		zIndex: {
			type: [String, Number],
			default: 0
		},
		
		title: {
			type: String,
			default: ''
		},
		
		cancelText: {
			type: String,
			default: '取消'
		},
		
		confirmText: {
			type: String,
			default: '确认'
		}
	},
	data() {
		return {
			years: [],
			months: [],
			days: [],
			hours: [],
			minutes: [],
			seconds: [],
			year: 0,
			month: 0,
			day: 0,
			hour: 0,
			minute: 0,
			second: 0,
			reset: false,
			startDate: '',
			endDate: '',
			valueArr: [],
			province: 0,
			city: 0,
			area: 0,
			moving: false 
		};
	},
	mounted() {
		this.init();
	},
	computed: {
		propsChange() {
			
			return `${this.mode}-${this.defaultTime}`;
		},
		uZIndex() {
			
			return this.zIndex ? this.zIndex : this.$u.zIndex.popup;
		}
	},
	watch: {
		propsChange() {
			this.reset = true;
			setTimeout(() => this.init(), 10);
		},
		year(){
			if(this.params.month){
				this.setMonths()
			}
			if(this.params.day){
				this.setDays()
			}
			if(this.params.hour){
				this.setHours()
			}
			if(this.params.minute){
				this.setMinutes()
			}
		},
		month(){
			if(this.params.day){
				this.setDays()
			}
			if(this.params.hour){
				this.setHours()
			}
			if(this.params.minute){
				this.setMinutes()
			}
		},
		day(){
			if(this.params.hour){
				this.setHours()
			}
			if(this.params.minute){
				this.setMinutes()
			}
		},
		hour(){
			if(this.params.minute){
				this.setMinutes()
			}
		},
		
		value(n) {
			if (n) {
				this.reset = true;
				setTimeout(() => this.init(), 10);
			}
		}
	},
	methods: {
		
		pickstart() {
			// #ifdef MP-WEIXIN
			this.moving = true;
			// #endif
		},
		
		pickend() {
			// #ifdef MP-WEIXIN
			this.moving = false;
			// #endif
		},
		
		getItemValue(item, mode) {
			
			
			if (this.mode == mode) {
				return typeof item == 'object' ? item[this.rangeKey] : item;
			}
		},
		
		formatNumber(num) {
			return +num < 10 ? '0' + num : String(num);
		},
		
		generateArray: function(start, end) {
			
			start = Number(start);
			end = Number(end);
			end = end > start ? end : start;
			
			return [...Array(end + 1).keys()].slice(start);
		},
		getIndex: function(arr, val) {
			let index = arr.indexOf(val);
			
			return ~index ? index : 0;
		},
		
		initTimeValue() {
			
			let fdate = this.defaultTime.replace(/\-/g, '/');
			fdate = fdate && fdate.indexOf('/') == -1 ? `2020/01/01 ${fdate}` : fdate;
			let time = null;
			if (fdate) time = new Date(fdate);
			else time = new Date();
			
			this.year = time.getFullYear();
			this.month = Number(time.getMonth()) + 1;
			this.day = time.getDate();
			this.hour = time.getHours();
			this.minute = time.getMinutes();
			this.second = time.getSeconds();
		},
		init() {
			this.valueArr = [];
			this.reset = false;
			if (this.mode == 'time') {
				this.initTimeValue();
				if (this.params.year) {
					this.valueArr.push(0);
					this.setYears();
				}
				if (this.params.month) {
					this.valueArr.push(0);
					this.setMonths();
				}
				if (this.params.day) {
					this.valueArr.push(0);
					this.setDays();
				}
				if (this.params.hour) {
					this.valueArr.push(0);
					this.setHours();
				}
				if (this.params.minute) {
					this.valueArr.push(0);
					this.setMinutes();
				}
				if (this.params.second) {
					this.valueArr.push(0);
					this.setSeconds();
				}
			}else if (this.mode == 'selector') {
				this.valueArr = this.defaultSelector;
			} else if (this.mode == 'multiSelector') {
				this.valueArr = this.defaultSelector;
				this.multiSelectorValue = this.defaultSelector;
			}
			this.$forceUpdate();
		},
		
		setYears() {
			
			this.years = this.generateArray(this.start.year, this.end.year);
			
			this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.years, this.year));
		},
		setMonths() {
			if(this.start.year==this.end.year){
				this.months = this.generateArray(this.start.month, this.end.month);
			}else if(this.year == this.start.year){
				this.months = this.generateArray(this.start.month, 12);
			}else if(this.year == this.end.year){
				this.months = this.generateArray(1, this.end.month);
			}else{
				this.months = this.generateArray(1, 12);
			}
			this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.months, this.month));
		},
		setDays() {
			let totalDays = new Date(this.year, this.month, 0).getDate();
			if(this.start.year==this.end.year&&this.start.month==this.end.month){
				this.days = this.generateArray(this.start.day, this.end.day);
			}else if(this.year == this.start.year&&this.month == this.start.month){
				this.days = this.generateArray(this.start.day, totalDays);
			}else if(this.year == this.end.year&&this.month == this.end.month){
				this.days = this.generateArray(1, this.end.day);
			}else{
				this.days = this.generateArray(1, totalDays);
			}
			let index = 0;
			
			
			if (this.params.year){
				index++
			}
			if(this.params.month){
				index++
			}
			
			
			if(this.day > this.days.slice(-1)[0]){
				this.day = this.days.slice(-1)[0];
			} 
			if(this.day < this.days.slice(0,1)[0]){
				this.day = this.days.slice(0,1)[0];
			} 
			this.valueArr.splice(index, 1, this.getIndex(this.days, this.day));
		},
		setHours() {
			if(this.start.year==this.end.year&&this.start.month==this.end.month&&this.start.day==this.end.day){
				this.hours = this.generateArray(this.start.hour, this.end.hour);
			}else if(this.year == this.start.year&&this.month == this.start.month&&this.day == this.start.day){
				this.hours = this.generateArray(this.start.hour, 23);
			}else if(this.year == this.end.year&&this.month == this.end.month&&this.day == this.end.day){
				this.hours = this.generateArray(0, this.end.hour);
			}else{
				this.hours = this.generateArray(0, 23);
			}
			let index = 0
			if(this.params.year){
				index++
			}
			if(this.params.month){
				index++
			}
			if(this.params.day){
				index++
			}
			
			if(this.hour > this.hours.slice(-1)[0]){
				this.hour = this.hours.slice(-1)[0];
			} 
			
			if(this.hour < this.hours.slice(0,1)[0]){
				this.hour = this.hours.slice(0,1)[0];
			} 
			this.valueArr.splice(index, 1, this.getIndex(this.hours, this.hour));
		},
		setMinutes() {
			if(this.start.year==this.end.year&&this.start.month==this.end.month&&this.start.day==this.end.day&&this.start.hour==this.end.hour){
				this.minutes = this.generateArray(this.start.minute, this.end.minute);
			}else if(this.year == this.start.year&&this.month == this.start.month&&this.day == this.start.day&&this.hour == this.start.hour){
				this.minutes = this.generateArray(this.start.minute, 59);
			}else if(this.year == this.end.year&&this.month == this.end.month&&this.day == this.end.day&&this.hour == this.end.hour){
				this.minutes = this.generateArray(0, this.end.minute);
			}else{
				this.minutes = this.generateArray(0, 59);
			}
			let index = 0
			if(this.params.year){
				index++
			}
			if(this.params.month){
				index++
			}
			if(this.params.day){
				index++
			}
			if(this.params.hour){
				index++
			}
			
			if(this.minute > this.minutes.slice(-1)[0]){
				this.minute = this.minutes.slice(-1)[0];
			} 
			
			if(this.minute < this.minutes.slice(0,1)[0]){
				this.minute = this.minutes.slice(0,1)[0];
			}
			this.valueArr.splice(index, 1, this.getIndex(this.minutes, this.minute));
		},
		setSeconds() {
			this.seconds = this.generateArray(0, 59);
			this.valueArr.splice(this.valueArr.length - 1, 1, this.getIndex(this.seconds, this.second));
		},
		close() {
			this.$emit('input', false);
		},
		
		change(e) {
			this.valueArr = e.detail.value;
			let i = 0;
			if (this.mode == 'time') {
				
				
				if (this.params.year) this.year = this.years[this.valueArr[i++]];
				if (this.params.month) this.month = this.months[this.valueArr[i++]];
				if (this.params.day) this.day = this.days[this.valueArr[i++]];
				if (this.params.hour) this.hour = this.hours[this.valueArr[i++]];
				if (this.params.minute) this.minute = this.minutes[this.valueArr[i++]];
				if (this.params.second) this.second = this.seconds[this.valueArr[i++]];
			} else if (this.mode == 'multiSelector') {
				let index = null;
				
				this.defaultSelector.map((val, idx) => {
					if (val != e.detail.value[idx]) index = idx;
				});
				
				if (index != null) {
					this.$emit('columnchange', {
						column: index,
						index: e.detail.value[index]
					});
				}
			}
		},
		
		getResult(event = null) {
			// #ifdef MP-WEIXIN
			if (this.moving) return;
			// #endif
			let result = {};
			
			if (this.mode == 'time') {
				if (this.params.year) result.year = this.formatNumber(this.year || 0);
				if (this.params.month) result.month = this.formatNumber(this.month || 0);
				if (this.params.day) result.day = this.formatNumber(this.day || 0);
				if (this.params.hour) result.hour = this.formatNumber(this.hour || 0);
				if (this.params.minute) result.minute = this.formatNumber(this.minute || 0);
				if (this.params.second) result.second = this.formatNumber(this.second || 0);
				if (this.params.timestamp) result.timestamp = this.getTimestamp();
			} else if (this.mode == 'selector') {
				result = this.valueArr;
			} else if (this.mode == 'multiSelector') {
				result = this.valueArr;
			}
			if (event) this.$emit(event, result);
			this.close();
		},
		
		getTimestamp() {
			
			let time = this.year + '/' + this.month + '/' + this.day + ' ' + this.hour + ':' + this.minute + ':' + this.second;
			return new Date(time).getTime() / 1000;
		}
	}
};
</script>

<style lang="scss" scoped>
@mixin vue-flex($direction: row) {
	/* #ifndef APP-NVUE */
	display: flex;
	flex-direction: $direction;
	/* #endif */
}
.u-datetime-picker {
	position: relative;
	z-index: 999;
}

.u-picker-view {
	height: 100%;
	box-sizing: border-box;
}

.u-picker-header {
	width: 100%;
	height: 90rpx;
	padding: 0 40rpx;
	@include vue-flex;
	justify-content: space-between;
	align-items: center;
	box-sizing: border-box;
	font-size: 30rpx;
	background: #fff;
	position: relative;
}

.u-picker-header::after {
	content: '';
	position: absolute;
	border-bottom: 1rpx solid #eaeef1;
	-webkit-transform: scaleY(0.5);
	transform: scaleY(0.5);
	bottom: 0;
	right: 0;
	left: 0;
}

.u-picker__title {
	color: $u-content-color;
}

.u-picker-body {
	width: 100%;
	height: 500rpx;
	overflow: hidden;
	background-color: #fff;
}

.u-column-item {
	@include vue-flex;
	align-items: center;
	justify-content: center;
	font-size: 32rpx;
	color: $u-main-color;
	padding: 0 8rpx;
}

.u-text {
	font-size: 24rpx;
	padding-left: 8rpx;
}

.u-btn-picker {
	padding: 16rpx;
	box-sizing: border-box;
	text-align: center;
	text-decoration: none;
}

.u-opacity {
	opacity: 0.5;
}

.u-btn-picker--primary {
	color: $u-type-primary;
}

.u-btn-picker--tips {
	color: $u-tips-color;
}
</style>
